import { _decorator, Component, instantiate, math, Node, Pool, Prefab, v3 } from 'cc';
import { ModuleBase } from '../../../FrameWork3.8.6/FrameWork/Module/ModuleBase';
import { Emitter } from '../../../FrameWork3.8.6/FrameWork/Common/Emitter';
import { EnemyBossDt, EnemyShiBingDt, ShiBingDt } from '../../../FrameWork3.8.6/FrameWork/Common/CommonInterface';
import { ModuleMgr } from '../../../FrameWork3.8.6/FrameWork/Module/ModuleMgr';
import { PlayerLayer } from './PlayerLayer';
import { ResMgr } from '../../../FrameWork3.8.6/FrameWork/Res/ResMgr';
import { BundleConfig } from '../../../FrameWork3.8.6/FrameWork/NeedToChange/BundleConfig';
import { ShiBingBase } from '../Base/ShiBingBase';
import { GameManager } from '../Manager/GameManager';
import { DataMgr } from '../../../FrameWork3.8.6/FrameWork/Data/DataMgr';
import { EnemyBossDtMgr, EnemyShiBingDtMgr, ShiBingDtMgr } from '../../../FrameWork3.8.6/FrameWork/Data/DataBaseMgr';
import { EnemyBoss } from '../Object/EnemyBoss';
import { CharacterBase } from '../Base/CharacterBase';
import { UIManager } from '../../../FrameWork3.8.6/FrameWork/UIFramework/UIManager';
import { PropLayer } from './PropLayer';
const { ccclass, property } = _decorator;

@ccclass('ShiBingLayer')
export class ShiBingLayer extends ModuleBase {
    //管理所有兵种对象池的容器
    private _mapShiBingNodePool:Map<string,Pool<Node>>=new Map();

    //所有士兵类型的预制体名字
    private _arrShiBingPrefabName:string[]=["Spearman","Archerman","Shieldman"];

    //管理玩家兵种脚本的容器
    private _mapShiBing:Map<number,ShiBingBase[]>=new Map();

    //管理敌人兵种脚本的容器
    private _mapEnemyShiBing:Map<number,ShiBingBase[]>=new Map();

    //该关卡一共要生成的士兵数量
    private _totalEnemyNum:number=0;
    //总的敌人波数,固定为3  
    private _waveNum:number=3;
    //当前波数
    private _curNum:number=0;
    //每一波的敌人数量数组
    private _arrWaveNum:number[]=[];

    //初始化关卡的敌人士兵数据
    private _arrEnemyShiBingDt:EnemyShiBingDt[]=[];

    //敌人Boss数据数组
    private _arrEnemyBossDt:EnemyBossDt[]=[];

    //敌人Boss对象池的容器
    private _mapEnemyBossNodePool:Map<string,Pool<Node>>=new Map();

    //存储敌人boss的容器
    private _mapEnemyBoss:Map<number,EnemyBoss[]>=new Map();

    //名字标识
    private _titleNum:number=0;

    
    
    onInit(...rest: any[]): void {
        //生成士兵对象池
        for(let prefabName of this._arrShiBingPrefabName){
            this.initNodePool(prefabName);
        }
        //注册生成玩家士兵的方法
        Emitter.instance.on("addPlayerShiBing",this.addPlayerShiBing,this);

        //初始化当前关卡敌人数据
        this.initEnemyShiBing();
        //拿到对应Boss的对象池
        for(let enemyBossDt of this._arrEnemyBossDt){
            let prefab=ResMgr.instance.getRes<Prefab>(BundleConfig.Game.name,enemyBossDt.prefabName);
            let nodePool=new Pool<Node>(()=>{
                let node=instantiate(prefab);
                return node;
            },2,(node:Node)=>{
                node.destroy();
            })
            this._mapEnemyBossNodePool.set(enemyBossDt.prefabName,nodePool);
        }
        
        
    }

    //初始化对象池的方法
    initNodePool(prefabName:string){
        //获取对应士兵预制体
        let prefab=ResMgr.instance.getRes<Prefab>(BundleConfig.ShiBingType.name,prefabName);
        let nodePool=new Pool<Node>(()=>{
            let node=instantiate(prefab);
            return node;
        },5,(node:Node)=>{
            node.destroy();
        })
        this._mapShiBingNodePool.set(prefabName,nodePool);
    }

    //真正添加玩家士兵的方法
    addPlayerShiBing(arrShiBingDt:ShiBingDt[],num:number){
        
        //根据玩家生成的位置左边一段距离生成玩家士兵
        let player=ModuleMgr.instance.getModule<PlayerLayer>("_PlayerLayer").player;
        let playerNode=player.node;
        for(let i=0;i<num;i++){
            let shiBingDt=arrShiBingDt[i];
            let shiBingNode=this._mapShiBingNodePool.get(shiBingDt.prefabName).alloc();
            shiBingNode.parent=this.node.getChildByName("PlayerShiBingLayer");
            shiBingNode.setPosition(v3(playerNode.position.x-150*(i+1),playerNode.position.y));
            let shiBingTs=shiBingNode.getComponent(ShiBingBase);
            let arrShiBing=this._mapShiBing.get(shiBingDt.id)
            if(!arrShiBing){
                arrShiBing=[];
            }
            this._titleNum++;
            arrShiBing.push(shiBingTs);
            this._mapShiBing.set(shiBingDt.id,arrShiBing);
            //调用玩家士兵初始化方法
            shiBingTs.onInit(shiBingDt,v3(2820,shiBingNode.position.y),30,shiBingDt.camp+shiBingDt.name+this._titleNum);
        }


    }

    //初始化当前关卡敌人士兵数据的方法
    initEnemyShiBing(){
        //初始化关卡的敌人士兵ID
        //这里需要遍历识别是否有boss
        let arrEnemyID=[];
        for(let id of GameManager.instance.enemyID){
            if(id.toString().charAt(0)=="5"){
                //说明是敌人兵种
                arrEnemyID.push(id);
                continue;
            }
            let enemyBossDt=DataMgr.instance.getMgr<EnemyBossDtMgr>("EnemyBossDtMgr").getDataByID<EnemyBossDt>(id);
            if(enemyBossDt){
                this._arrEnemyBossDt.push(enemyBossDt);
            }
        }
        
        //当前关卡的敌人士兵数量
        this._totalEnemyNum=GameManager.instance.requirements[0];
       
        for(let id of arrEnemyID){
            let enemyShiBingDt=DataMgr.instance.getMgr<EnemyShiBingDtMgr>("EnemyShiBingDtMgr").getDataByID<EnemyShiBingDt>(id);
            this._arrEnemyShiBingDt.push(enemyShiBingDt);
        }
        //随机值确定每一波的数量
        let firstEnemyNum=Math.floor(math.random()*this._totalEnemyNum/3);
        let secondEnemyNum=Math.floor(math.random()*this._totalEnemyNum/3);
        let thirdEnemyNum=this._totalEnemyNum-firstEnemyNum-secondEnemyNum;
        //初始化当前关卡每一波敌人数量
        this._arrWaveNum=[firstEnemyNum,secondEnemyNum,thirdEnemyNum];
        //开始第一波敌人的生成
        this.startWave(this._arrWaveNum[0]);
        
        
    }
    //开始敌人波数生成
    startWave(enemyNum:number){
        let spawned:number=0;//当前波数已经生成的数量
        this.schedule(()=>{
            //如果当前波数数量还没有生成完
            if(spawned<enemyNum){
                let random=Math.floor(math.random()*this._arrEnemyShiBingDt.length);
                let enemyShiBingDt=this._arrEnemyShiBingDt[random];
                this.spawnEnemyShiBing(enemyShiBingDt);
                spawned++
            }
            else{
                //关闭所有计时器
                this.unscheduleAllCallbacks();
                //当前波数生成完开启下一波
                this.nextWave();
                
            }
        },math.random()*1+1)//1-2秒一个敌人
    }

    //下一波敌人生成
    nextWave(){
        if(this._curNum<this._waveNum){
            this._curNum++;//当前波数加一
            this.schedule(()=>{
                this.startWave(this._arrWaveNum[this._curNum])
            },math.random()*3+2)//2-5秒一波
        }
        else{
            console.log("当前关卡的所有敌人士兵生成完，可以生成boss");
            for(let enemyBossDt of this._arrEnemyBossDt){
                this.spawnEnemyBoss(enemyBossDt);
            }

        }
    }
    //生成单个敌人士兵的方法
    spawnEnemyShiBing(enemyShiBingDt:EnemyShiBingDt){
        //拿到当前敌人数据对应的对象池
        let nodePool=this._mapShiBingNodePool.get(enemyShiBingDt.prefabName);
        //实例化物体,并且设置父亲,与出生点
        let enemyShiBingNode=nodePool.alloc();
        enemyShiBingNode.parent=this.node.getChildByName("EnemyShiBingLayer");
        enemyShiBingNode.setPosition(v3(2820,enemyShiBingNode.position.y));
        //获取士兵基类脚本，调用初始化脚本,并且存储
        let shiBingBase=enemyShiBingNode.getComponent(ShiBingBase);
        shiBingBase.onInit(enemyShiBingDt,v3(-900,0),-30,enemyShiBingDt.camp+enemyShiBingDt.name+ this._titleNum);
        let arrShiBing=this._mapEnemyShiBing.get(enemyShiBingDt.id);
        if(!arrShiBing){
            arrShiBing=[];
        }
        this._titleNum++
        arrShiBing.push(shiBingBase);
        this._mapEnemyShiBing.set(enemyShiBingDt.id,arrShiBing);

    }
    
    //生成敌人Boss的方法
    spawnEnemyBoss(enemyBossDt:EnemyBossDt){
        let nodePool=this._mapEnemyBossNodePool.get(enemyBossDt.prefabName);
        let enemyBossNode=nodePool.alloc();
        enemyBossNode.parent=this.node.getChildByName("EnemyBossLayer");
        enemyBossNode.setPosition(v3(2820,enemyBossNode.position.y));
        let enemyBossTs=enemyBossNode.getComponent(EnemyBoss);
        enemyBossTs.onInit(enemyBossDt,-1);
        let arrEnemyBoss=this._mapEnemyBoss.get(enemyBossDt.id);
        if(!arrEnemyBoss){
            arrEnemyBoss=[];
        }
        arrEnemyBoss.push(enemyBossTs);
        this._mapEnemyBoss.set(enemyBossDt.id,arrEnemyBoss);

    }
    

    



    //移除某个士兵的方法
    deleteShiBing(shiBingBase:ShiBingBase){
        //先获取是哪个对象池
        let nodePool=this._mapShiBingNodePool.get(shiBingBase.shiBingDt.prefabName);
        //判断是哪个阵营
        if(shiBingBase.shiBingDt.camp=="玩家"){
            let arrShiBing=this._mapShiBing.get(shiBingBase.shiBingDt.id);
            for(let i=0;i<arrShiBing.length;i++){
                if(shiBingBase.name==arrShiBing[i].name){
                    arrShiBing.splice(i,1);
                    this._mapShiBing.set(shiBingBase.shiBingDt.id,arrShiBing);
                    shiBingBase.node.parent=null;
                    nodePool.free(shiBingBase.node);
                    return;
                }
            }
        }
        else{
            let arrShiBing=this._mapEnemyShiBing.get(shiBingBase.shiBingDt.id);
            for(let i=0;i<arrShiBing.length;i++){
                if(shiBingBase.name==arrShiBing[i].name){
                    arrShiBing.splice(i,1);
                    this._mapEnemyShiBing.set(shiBingBase.shiBingDt.id,arrShiBing);
                    //发送生成道具的消息
                    Emitter.instance.emit("addProp",ModuleMgr.instance.getModule<PropLayer>("PropLayer"),shiBingBase.node)
                    shiBingBase.node.parent=null;
                    nodePool.free(shiBingBase.node);
                    //当移除一个玩家士兵时给player发送消息

                    //console.log(UIManager.instance.getUI("MainUI"));
                    Emitter.instance.emit("killEnemy",UIManager.instance.getUI("MainUI"),1);
                    return;
                }
            }
        }
       
    }


    /**
     * 获取一个范围内的士兵
     * @param satrtPosX 起点X
     * @param endPosX 终点X
     * @param camp 阵营
     * @returns 
     */
    getArrShiBing(satrtPosX:number,endPosX:number,camp:string){
        let map:Map<number,ShiBingBase[]>=new Map();
        let arrShiBingBase:ShiBingBase[]=[];
        if(camp=="玩家"){
            map=this._mapEnemyShiBing;
        }
        else{
            map=this._mapShiBing;
        }
        for(let arrshiBing of map.values()){
            for(let shiBingBase of arrshiBing){
                if(shiBingBase.node.position.x>=satrtPosX&&shiBingBase.node.position.x<=endPosX){
                    arrShiBingBase.push(shiBingBase);
                }
            }  
        }
        return arrShiBingBase;
    }


    //移除某个boss的方法
    deleteBoss(enemyBoss:CharacterBase){
        let nodePool=this._mapEnemyBossNodePool.get(enemyBoss.roleDt.prefabName);
        this._mapEnemyBoss.delete(enemyBoss.roleDt.id);
        enemyBoss.node.parent=null;
        nodePool.free(enemyBoss.node);
        let values=Array.from(this._mapEnemyBoss.values());
        if(values.length==0){
            //发送游戏胜利
            Emitter.instance.emitNoTarget("GameOver",true);
        }
        
    }

    //获取一个范围内玩家或者敌人boss的方法
    getPlayerOrBoss(satrtPosX:number,endPosX:number,camp:string){
        let arrCamp:Node[]=[]
        if(camp=="玩家"){
            for(let arrEnemyBoss of this._mapEnemyBoss.values()){
                for(let enemyBoss of arrEnemyBoss){
                    if(enemyBoss.node.position.x>=satrtPosX&&enemyBoss.node.position.x<=endPosX){
                        arrCamp.push(enemyBoss.node);
                    }
                }
            }
        }
        else{
            let playerNode=ModuleMgr.instance.getModule<PlayerLayer>("_PlayerLayer").player.node;
            if(playerNode.position.x>=satrtPosX&&playerNode.position.x<=endPosX){
                arrCamp.push(playerNode);
            }
        }
        return arrCamp;
    }

    //获取一个范围内的敌方阵营
    getCamp(satrtPosX:number,endPosX:number,camp:string){
        let arrCamp:Node[]=[];
        arrCamp=this.getPlayerOrBoss(satrtPosX,endPosX,camp);
        let arrshibingbase=this.getArrShiBing(satrtPosX,endPosX,camp)
        for(let shibingbase of arrshibingbase){
            arrCamp.push(shibingbase.node)
        }
        return arrCamp;
    }

    //统一管理所有士兵的移动,以及生成敌人士兵
    onUpdate(dt: number, ...rest: any[]): void {
        for(let arrShiBing of this._mapShiBing.values()){
            for(let values of arrShiBing){
                 values.onUpdate(dt);
            }
        }
        for(let arrEnemyShiBing of this._mapEnemyShiBing.values()){
            for(let values of arrEnemyShiBing){
                 values.onUpdate(dt);
            }
        }
        for(let arrEnemyBoss of this._mapEnemyBoss.values()){
            for(let values of arrEnemyBoss){
                values.onUpdate(dt);
            }
        }
        
    }
}


